package com.googlecode.likesql.context;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import com.googlecode.likesql.constant.Keyword;
import com.googlecode.likesql.constant.SqlChar;
import com.googlecode.likesql.converter.Converter;
import com.googlecode.likesql.converter.ConverterTable;

/**
 * The InsertSqlContext class represents a context for SQL insert statement.
 * 
 * @author Johny Huang
 *
 */
public class InsertSqlContext implements SqlContext{

	private List columnList;

	private List valueList;
	
	private String table;
	
	public InsertSqlContext(){
		columnList=new LinkedList();
		valueList=new LinkedList();
	}
	
	/**
	 * Adds a column and a matched value.
	 * 
	 * @param column
	 * @param value
	 * @return
	 */
	public InsertSqlContext addColumnValue(String column,Object value){
		columnList.add(column);
		valueList.add(value);
		return this;
	}
	
	/**
	 * Sets the table.
	 * 
	 * @param table
	 * @return
	 */
	public InsertSqlContext setTable(String table){
		this.table=table;
		return this;
	}
	
	protected Converter getConverter(Object value) {
		String clazzName = null;
		if (value != null) {
			clazzName = value.getClass().getName();
		}
		return ConverterTable.getInstance().getConverter(clazzName);

	}
	
	protected String convertToTpl(Object value) {
		Converter cvt = getConverter(value);
		return cvt.toTemplate(value);
	}
	
	protected String convertToSql(Object value) {
		Converter cvt = getConverter(value);
		return cvt.toSql(value);
	}
	
	public String getSql() {
		StringBuffer buffer = new StringBuffer();
		buffer.append(Keyword.INSERT_INTO).append(SqlChar.SP).append(table);

		int i = 0;
		int lastIndex = 0;
		Iterator it=null;
		if (!columnList.isEmpty()){
			buffer.append(SqlChar.SP).append(SqlChar.LP);
			
			it=columnList.iterator();
			lastIndex = columnList.size() - 1;
			for (; i < lastIndex; i++) {
				buffer.append(it.next()).append(SqlChar.COMMA);
			}
			buffer.append(it.next()).append(SqlChar.RP);
		}

		buffer.append(SqlChar.SP).append(Keyword.VALUES).append(SqlChar.LP);

		if (!valueList.isEmpty()) {
			it=valueList.iterator();
			Object obj=null;
			while(it.hasNext()){
				obj=it.next();
				buffer.append(convertToSql(obj));
				if(it.hasNext()){
					buffer.append(SqlChar.COMMA);
				}
			}
		}
		buffer.append(SqlChar.RP);

		return buffer.toString();
	}

	public String getTemplate() {
		StringBuffer buffer = new StringBuffer();
		buffer.append(Keyword.INSERT_INTO).append(SqlChar.SP).append(table);

		int i = 0;
		int lastIndex = 0;
		Iterator it=null;
		if (!columnList.isEmpty()){
			buffer.append(SqlChar.SP).append(SqlChar.LP);
			it=columnList.iterator();
			lastIndex = columnList.size() - 1;
			for (; i < lastIndex; i++) {
				buffer.append(it.next()).append(SqlChar.COMMA);
			}
			buffer.append(it.next()).append(SqlChar.RP);
		}

		buffer.append(SqlChar.SP).append(Keyword.VALUES).append(SqlChar.LP);
		if (!valueList.isEmpty()) {
			it=valueList.iterator();
			Object obj=null;
			while(it.hasNext()){
				obj=it.next();
				buffer.append(convertToTpl(obj));
				if(it.hasNext()){
					buffer.append(SqlChar.COMMA);
				}
			}
		}
		buffer.append(SqlChar.RP);

		return buffer.toString();
	}

	public PreparedStatement getPreStatement(Connection con)
			throws SQLException {
		PreparedStatement stmt=con.prepareStatement(getTemplate());
		Iterator it=valueList.iterator();
		int count=1;
		while(it.hasNext()){
		    stmt.setObject(count++,it.next());
		}
		return stmt;
	}
	
	public List getValueList(){
		return valueList;
	}

}
